<template>
    <div ref="tree" class="tree">
        <div class="tree__inner">
            <AppTreeNode
                v-for="(node, index) in store.clonedNodes"
                ref="node"
                :key="node.id"
                :node="node"
                :nodes="store.clonedNodes!"
                :index="index"
                :hovered-node-id="hoveredNodeId"
            >
                <template #default="{ node: childNode, deep }">
                    <slot
                        :node="childNode"
                        :deep="deep"
                        :hovered-node-id="hoveredNodeId"
                    />
                </template>
            </AppTreeNode>
        </div>
    </div>
</template>

<script setup lang="ts">
import type { Ref } from 'vue'
import { provide, ref, watch } from 'vue'
import { store } from './composable'
import type { Node } from './types'
import { clone } from './helpers'

interface Props {
    modelValue: Node[] | any[]
    selectedId?: string
    createGhostEl?: Function
    // Колбек должен вернуть состояние для props.isHighlighted AppTreeNode
    contextMenuHandler: () => Promise<boolean>
    focusHandler?: (isFocused: Ref) => void
}

interface Emits {
    (e: 'update:modelValue', value: Node[]): void
    (e: 'click:node', value: string): void
}

const emit = defineEmits<Emits>()
const props = withDefaults(defineProps<Props>(), {
    contextMenuHandler: () => Promise.resolve(true)
})

const hoveredNodeId = ref('')
const isHoveredByIdDisabled = ref(false)

const cloneNodes = () => {
    store.clonedNodes = clone(props.modelValue) as Node[]
}

const updateValue = () => emit('update:modelValue', store.clonedNodes)
const clickNode = (id: string) => emit('click:node', id)

const setHoveredNodeId = (id: string) => {
    if (isHoveredByIdDisabled.value) return
    hoveredNodeId.value = id
}

provide('updateValue', updateValue)
provide('clickNode', clickNode)
provide('contextMenuHandler', props.contextMenuHandler)
provide('isHoveredByIdDisabled', isHoveredByIdDisabled)
provide('focusHandler', props.focusHandler)

defineExpose({
    setHoveredNodeId
})

watch(
    () => props.modelValue,
    () => cloneNodes(),
    {
        immediate: true
    }
)

watch(
    () => props.selectedId,
    () => {
        store.selectedId = props.selectedId
    },
    { immediate: true }
)
</script>

<style lang="scss" scoped>
.tree {
    &__inner {
        padding-top: 5px;
    }
}
</style>
